// A new namespace to hold our functions
frappe.configure_columns = {};

frappe.configure_columns.open_dialog = function(frm) {
    if (!frm.doc.reference_doctype) {
        frappe.throw(__('Please select a Reference DocType first.'));
        return;
    }

    // Ensure metadata for the parent DocType is loaded
    frappe.model.with_doctype(frm.doc.reference_doctype, () => {
        const table_fieldname = frm.doc.table_fieldname;
        if (!table_fieldname) {
            frappe.throw(__('Please enter a Table Fieldname.'));
            return;
        }

        // Now, this call will succeed because the meta for reference_doctype is loaded
        const table_docfield = frappe.meta.get_docfield(frm.doc.reference_doctype, table_fieldname);
        if (!table_docfield || table_docfield.fieldtype !== 'Table') {
            frappe.throw(__('Invalid Table Fieldname or field is not a child table.'));
            return;
        }

        const child_doctype = table_docfield.options;

        // Ensure metadata for the child DocType is also loaded
        frappe.model.with_doctype(child_doctype, () => {
            const dialog = new frappe.ui.Dialog({
                title: __("Configure Columns"),
                fields: [
                    {
                        fieldtype: "HTML",
                        fieldname: "fields_html",
                    },
                ],
                primary_action_label: __("Update"),
                primary_action: (values) => {
                    const columns = frappe.configure_columns.get_columns_from_dialog(dialog);
                    frappe.configure_columns.save_layout(frm, columns);
                    dialog.hide();
                }
            });

            const state = {
                selected_columns_for_grid: JSON.parse(frm.doc.data || '[]'),
                docfields: frappe.get_meta(child_doctype).fields,
                fields_html_wrapper: dialog.get_field("fields_html").$wrapper[0],
                dialog: dialog
            };

            frappe.configure_columns.prepare_wrapper(state);
            frappe.configure_columns.render_columns(state);
            
            $(state.fields_html_wrapper).find(".add-new-fields").click(() => {
                frappe.configure_columns.open_column_selector(state);
            });

            dialog.show();
        });
    });
};

frappe.configure_columns.get_columns_from_dialog = function(dialog) {
    const columns = [];
    const fields = $(dialog.fields_dict.fields_html.$wrapper).find(".fields_order") || [];
    fields.each((idx) => {
        columns.push({
            fieldname: $(fields[idx]).attr("data-fieldname"),
            columns: cint($(fields[idx]).find(".column-width").val()),
        });
    });
    return columns;
};

frappe.configure_columns.save_layout = function(frm, columns) {
    const serialized_data = JSON.stringify(columns);
    frm.set_value('data', serialized_data);
    frappe.show_alert(__('Grid layout configuration saved.'));
};

frappe.configure_columns.prepare_wrapper = function(state) {
    $(`
        <div class='form-group'>
            <div class='row' style='margin-bottom:10px;'>
                <div class='col-1'></div>
                <div class='col-6' style='padding-left:20px;'>
                    ${__("Fieldname").bold()}
                </div>
                <div class='col-4'>
                    ${__("Column Width").bold()}
                </div>
                <div class='col-1'></div>
            </div>
            <div class='control-input-wrapper selected-fields'>
            </div>
            <p class='help-box small text-muted'>
                <a class='add-new-fields text-muted'>
                    + ${__("Add / Remove Columns")}
                </a>
            </p>
        </div>
    `).appendTo(state.fields_html_wrapper);
};

frappe.configure_columns.render_columns = function(state) {
    let fields_html = "";
    if (state.selected_columns_for_grid) {
        state.selected_columns_for_grid.forEach(d => {
            const docfield = state.docfields.find(f => f.fieldname === d.fieldname);
            if (!docfield) return;

            // Get the default width from the `d` object, which was populated in `prepare_fields_for_multicheck`
            const columns_width = d.columns || 2; 

            fields_html += `
                <div class='control-input flex align-center form-control fields_order sortable-handle sortable'
                    style='display: block; margin-bottom: 5px; padding: 0 8px; cursor: pointer; height: 32px;' data-fieldname='${
                        docfield.fieldname
                    }'
                    data-label='${docfield.label}' data-type='${docfield.fieldtype}'>
                    <div class='row'>
                        <div class='col-1' style='padding-top: 4px;'>
                            <a style='cursor: grabbing;'>${frappe.utils.icon("drag", "xs")}</a>
                        </div>
                        <div class='col-6' style='padding-top: 5px;'>
                            ${__(docfield.label, null, docfield.parent)}
                        </div>
                        <div class='col-4' style='padding-top: 2px; margin-top:-2px;' title='${__("Columns")}'>
                            <input class='form-control column-width my-1 input-xs text-right'
                                style='height: 24px; max-width: 80px; background: var(--bg-color);'
                                value='${columns_width}'
                                data-fieldname='${docfield.fieldname}' style='background-color: var(--modal-bg); display: inline'>
                        </div>
                        <div class='col-1' style='padding-top: 3px;'>
                            <a class='text-muted remove-field' data-fieldname='${docfield.fieldname}'>
                                <i class='fa fa-trash-o' aria-hidden='true'></i>
                            </a>
                        </div>
                    </div>
                </div>`;
        });
    }

    $(state.fields_html_wrapper).find(".selected-fields").html(fields_html);
    
    // Sortable functionality
    new Sortable($(state.fields_html_wrapper).find(".selected-fields")[0], {
        handle: ".sortable-handle",
        draggable: ".sortable",
        onUpdate: () => {
            state.selected_columns_for_grid = [];
            const columns = $(state.fields_html_wrapper).find(".fields_order") || [];
            columns.each((idx) => {
                state.selected_columns_for_grid.push({
                    fieldname: $(columns[idx]).attr("data-fieldname"),
                    columns: cint($(columns[idx]).find(".column-width").val()),
                });
            });
        },
    });
    
    // Event handlers for removing fields
    $(state.fields_html_wrapper).find(".remove-field").click((e) => {
        const fieldname_to_remove = $(e.target).closest('a').data('fieldname');
        state.selected_columns_for_grid = state.selected_columns_for_grid.filter(c => c.fieldname !== fieldname_to_remove);
        $(e.target).closest('.fields_order').remove();
    });

    // Event handlers for column width changes
    $(state.fields_html_wrapper).find(".column-width").change((e) => {
        const fieldname = e.target.dataset.fieldname;
        const new_width = cint(e.target.value);

        if (new_width === 0) {
            e.target.value = e.target.defaultValue;
            frappe.throw(__("Column width cannot be zero."));
            return;
        }

        const column = state.selected_columns_for_grid.find(row => row.fieldname === fieldname);
        if (column) {
            column.columns = new_width;
            e.target.defaultValue = new_width;
        }
    });

    // Add keydown event listener for up/down arrow navigation
    $(state.fields_html_wrapper).find(".column-width").on('keydown', (e) => {
        const input = $(e.target);
        const current_row = input.closest('.fields_order');
        let next_row;

        if (e.key === 'ArrowDown') {
            next_row = current_row.next('.fields_order');
        } else if (e.key === 'ArrowUp') {
            next_row = current_row.prev('.fields_order');
        }

        if (next_row && next_row.length) {
            next_row.find('.column-width').focus().select();
            e.preventDefault(); // Prevents the browser from scrolling
        }
    });
};

frappe.configure_columns.open_column_selector = function(state) {
    const docfields = frappe.configure_columns.prepare_fields_for_multicheck(state);

    const d = new frappe.ui.Dialog({
        title: __("{0} Fields", [__(state.docfields[0].parent)]),
        fields: [
            {
                label: __("Select Fields"),
                fieldtype: "MultiCheck",
                fieldname: "fields",
                options: docfields,
                columns: 2,
                sort_options: false,
            },
        ],
        primary_action_label: __("Add"),
        primary_action: (values) => {
            const selected_fields = values.fields;
            state.selected_columns_for_grid = [];
            if (selected_fields) {
                selected_fields.forEach((selected_column) => {
                    // Find the original object from the prepared list which has the correct width
                    const prepared_field = docfields.find(f => f.value === selected_column);
                    
                    if (prepared_field) {
                        state.selected_columns_for_grid.push({
                            fieldname: prepared_field.value,
                            columns: prepared_field.columns, // Use the pre-calculated width
                        });
                    }
                });
                frappe.configure_columns.render_columns(state);
                d.hide();
            }
        },
    });
    d.show();
};

frappe.configure_columns.prepare_fields_for_multicheck = function(state) {
    const fields = [];
    const blocked_fields = frappe.model.no_value_type;
    const always_allow = ["Button"];
    
    const show_field = (f) => always_allow.includes(f) || !blocked_fields.includes(f);
    const selected_fields = state.selected_columns_for_grid.map(f => f.fieldname);

    // Helper function to determine default columns based on fieldtype
    const get_default_columns = (docfield) => {
        if (!docfield) return 2;
        const width_map = {
            'Int': 1,
            'Float': 1,
            'Check': 1
        };
        return width_map[docfield.fieldtype] || 2;
    };

    // First, add selected fields with their current configuration
    selected_fields.forEach(selectedField => {
        const selectedColumn = state.docfields.find(column => column.fieldname === selectedField);
        if (selectedColumn && !selectedColumn.hidden && show_field(selectedColumn.fieldtype)) {
            fields.push({
                label: __(selectedColumn.label, null, selectedColumn.parent),
                value: selectedColumn.fieldname,
                checked: true,
                columns: selectedColumn.columns || get_default_columns(selectedColumn)
            });
        }
    });

    // Then, add the rest of the fields with the new default logic
    state.docfields.forEach(column => {
        if (!selected_fields.includes(column.fieldname) && !column.hidden && show_field(column.fieldtype)) {
            fields.push({
                label: __(column.label, null, column.parent),
                value: column.fieldname,
                checked: false,
                columns: get_default_columns(column)
            });
        }
    });
    return fields;
};

frappe.configure_columns.update_grid_columns = function(frm) {
    const grid_layout_id = frm.doc.grid_layout;
    const table_fieldname = 'items'; // Change this to your child table's fieldname

    if (!grid_layout_id) {
        // If no layout is selected, remove the custom settings and re-render.
        const grid = frm.get_field(table_fieldname)?.grid;
        if (grid) {
            frappe.model.user_settings.remove(grid.doctype, 'GridView');
            grid.setup_visible_columns();
            grid.make_head();
            grid.reset_grid();
        }
        return;
    }

    // Attempt to get the document from the local cache first
    let layout_doc = frappe.get_doc('Grid Layout', grid_layout_id);

    // If not found in locals, fall back to a server call
    if (!layout_doc) {
        frappe.db.get_doc('Grid Layout', grid_layout_id).then(doc => {
            if (doc) {
                apply_grid_layout(frm, doc);
            }
        });
    } else {
        // If found locally, apply the layout immediately
        apply_grid_layout(frm, layout_doc);
    }
};

function apply_grid_layout(frm, layout_doc) {
    if (!layout_doc || !layout_doc.data || !layout_doc.table_fieldname) {
        console.error('Grid Layout document or its data is incomplete:', layout_doc);
        return;
    }
    const parent_doctype = layout_doc.reference_doctype;
    const table_fieldname = layout_doc.table_fieldname;
    let configured_columns_data;
    try {
        configured_columns_data = JSON.parse(layout_doc.data);
    } catch (e) {
        console.error("Error parsing layout_doc.data JSON:", e);
        return;
    }

    const grid = frm.get_field(table_fieldname)?.grid;

    if (!grid) {
        console.error(`Grid field "${table_fieldname}" not found or is not a grid on form ${frm.doctype}.`);
        return;
    }
    
    // Core Fix: Directly assign the parsed JSON data to the user settings cache.
    // This is exactly what the grid's setup_user_defined_columns method expects.
    if (!frappe.model.user_settings[parent_doctype]) {
        frappe.model.user_settings[parent_doctype] = {};
    }
    frappe.model.user_settings[parent_doctype]['GridView'][grid.doctype] = configured_columns_data;

    // Now simply trigger the grid's rendering methods. It will correctly use
    // the data we just put in the cache.
    grid.setup_visible_columns();
    grid.make_head();
    grid.reset_grid();
}

frappe.configure_columns.handle_switch_grid_layout_buttons = function(frm, table_fieldname) {
    // Ensure the view_filter field is ready
    if (!frm.fields_dict.view_filter) {
        console.error("Custom view filter field not found!");
        return;
    }

    // Get the linked doctype for the grid_layout field
    let linked_doctype = frm.get_field('grid_layout').df.options;
    if (!linked_doctype) {
        console.error("Grid layout field or its linked doctype not found!");
        return;
    }

    // Get current doctype for reference_doctype
    let reference_doctype = frm.doctype;
    
    // Use provided table_fieldname or default to 'items'
    table_fieldname = table_fieldname || 'items';

    // Get the current value of grid_layout to highlight the selected button
    let current_grid_layout = frm.doc.grid_layout || '';

    // Fetch all records from the linked doctype
    frappe.call({
        method: 'frappe.client.get_list',
        args: {
            doctype: linked_doctype,
            fields: ['name'],
            limit_page_length: 0 // Fetch all records
        },
        callback: function(r) {
            if (r.message) {
                let options = r.message;
                let html = '';

                // Build URL for new Grid Layout document with pre-filled values
                let new_doc_url = `/app/grid-layout/new-grid-layout-1?reference_doctype=${encodeURIComponent(reference_doctype)}&table_fieldname=${encodeURIComponent(table_fieldname)}`;
                
                // Add a light bronze button to open new Grid Layout form with pre-filled values
                html += `<div style="text-align: right; margin-bottom: 10px;">
                            <button class="btn" style="background-color: #D4A017; color: white;" onclick="window.open('${new_doc_url}', '_blank')">Add New ${linked_doctype}</button>
                         </div>`;

                // Build buttons for each option, highlighting the current grid_layout value
                options.forEach(function(opt) {
                    let is_selected = (opt.name === current_grid_layout) ? 'background-color: #90EE90; color: black;' : '';
                    html += `<button class="btn btn-default filter-btn" data-value="${opt.name}" style="margin-right: 5px; margin-bottom: 5px; ${is_selected}">${opt.name}</button>`;
                });

                // Set the HTML content in the view_filter field
                try {
                    frm.set_df_property('view_filter', 'options', html);
                    frm.refresh_field('view_filter');
                } catch (e) {
                    console.error("Error setting HTML for view_filter:", e);
                }

                // Attach click event handlers to the filter buttons
                frm.fields_dict.view_filter.$wrapper.find('.filter-btn').on('click', function() {
                    let val = $(this).data('value');
                    frm.set_value('grid_layout', val);
                    // Update button styles: reset all to default, then highlight the selected one
                    frm.fields_dict.view_filter.$wrapper.find('.filter-btn').css({
                        'background-color': '',
                        'color': ''
                    });
                    $(this).css({
                        'background-color': '#90EE90',
                        'color': 'black'
                    });
                });
            } else {
                console.error("No options fetched for linked doctype:", linked_doctype);
                // Set a fallback message in the HTML field
                frm.set_df_property('view_filter', 'options', '<p>No options available for Grid Layout.</p>');
                frm.refresh_field('view_filter');
            }
        },
        error: function(err) {
            console.error("Error fetching linked doctype options:", err);
            // Set a fallback message in the HTML field
            frm.set_df_property('view_filter', 'options', '<p>Error loading options. Please try again.</p>');
            frm.refresh_field('view_filter');
        }
    });    
}